/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.ui;

import java.io.File;

import java.util.ArrayList;
import java.util.Vector;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import phoside.PhosideInit;
import phoside.PhosphoProteins;
import phoside.PhosphoProteinsImpl;
import phoside.Proteins;

import phoside.data.util.PhosphoDataUtil;

import phoside.io.xml.PhosideXmlProteinsReader;
import phoside.io.xml.PhosideXmlProteinsWriter;
import phoside.io.xml.PhosphoProteinFieldValueFormatter;

import phoside.ui.task.ProteinsReadTask;
import phoside.ui.task.ProteinsWriteTask;
import phoside.ui.task.TaskUtil;

import phoside.util.FileExtensionsFilter;
import phoside.util.FilePathParser;

/**
 *
 * @author gjj
 */
public class MergeFileDialog extends javax.swing.JDialog {

    /** Creates new form Fasta2XmlDialog */
    public MergeFileDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        javax.swing.JPanel fromPanel = new javax.swing.JPanel();
        fromScrollPane = new javax.swing.JScrollPane();
        fromList = new javax.swing.JList();
        javax.swing.JPanel addRmvFromPanel = new javax.swing.JPanel();
        javax.swing.JButton addFromButton = new javax.swing.JButton();
        javax.swing.JButton rmvFromButton = new javax.swing.JButton();
        javax.swing.JPanel xmlPanel = new javax.swing.JPanel();
        javax.swing.JPanel xmlFilePanel = new javax.swing.JPanel();
        xmlFileTextField = new javax.swing.JTextField();
        javax.swing.JButton xmlFileButton = new javax.swing.JButton();
        javax.swing.JPanel OKPanel = new javax.swing.JPanel();
        OKBtn = new javax.swing.JButton();
        javax.swing.JButton cancelBtn = new javax.swing.JButton();
        javax.swing.JPanel opPanel = new javax.swing.JPanel();
        opComboBox = new javax.swing.JComboBox();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Merging files");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        fromPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("PHOSIDE XML files"));
        fromPanel.setLayout(new java.awt.GridBagLayout());

        fromScrollPane.setViewportView(fromList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        fromPanel.add(fromScrollPane, gridBagConstraints);

        addRmvFromPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        addFromButton.setText("Add a file");
        addFromButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addFromButtonActionPerformed(evt);
            }
        });
        addRmvFromPanel.add(addFromButton);

        rmvFromButton.setText("Remove selected file(s)");
        rmvFromButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rmvFromButtonActionPerformed(evt);
            }
        });
        addRmvFromPanel.add(rmvFromButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        fromPanel.add(addRmvFromPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(fromPanel, gridBagConstraints);

        xmlPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Save Merged PHOSIDE XML File to..."));
        xmlPanel.setMinimumSize(new java.awt.Dimension(400, 63));
        xmlPanel.setPreferredSize(new java.awt.Dimension(500, 63));
        xmlPanel.setLayout(new java.awt.GridBagLayout());

        xmlFilePanel.setLayout(new java.awt.GridBagLayout());

        xmlFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        xmlFilePanel.add(xmlFileTextField, gridBagConstraints);

        xmlFileButton.setText("Open");
        xmlFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                xmlFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        xmlFilePanel.add(xmlFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        xmlPanel.add(xmlFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(xmlPanel, gridBagConstraints);

        OKBtn.setText("   OK   ");
        OKBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKBtnActionPerformed(evt);
            }
        });
        OKPanel.add(OKBtn);

        cancelBtn.setText("Cancel");
        cancelBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelBtnActionPerformed(evt);
            }
        });
        OKPanel.add(cancelBtn);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(OKPanel, gridBagConstraints);

        opPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Operation"));
        opPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        opComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Union", "Intersection", "Difference" }));
        opPanel.add(opComboBox);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(opPanel, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void xmlFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_xmlFileButtonActionPerformed
        JFileChooser fc;
        String defFile = xmlFileTextField.getText();
        fc = new JFileChooser(PhosideInit.defaultPath);

        String ext = "xml";
        fc.setSelectedFile(new File(defFile));
        ArrayList<String> exts = new ArrayList<String>(1);
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Save to...");
        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            xmlFileTextField.setText(filePath);
        }
    }//GEN-LAST:event_xmlFileButtonActionPerformed

    private void OKBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKBtnActionPerformed
        if (fromFiles.size()<2) {
            JOptionPane.showMessageDialog(this, "Error: please select at lease two PHOSIDE XML files.");
            return;
        }

        String dirXml = xmlFileTextField.getText();
        if (dirXml.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify the xml file to save.");
            return;
        }

        if (!dirXml.toLowerCase().endsWith(".xml")) {
            dirXml += ".xml";
        }

        if (phoside.util.IOUtil.fileExist(dirXml)) {
            int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing xml file?",
                    null, JOptionPane.YES_NO_OPTION);
            if (ret==JOptionPane.NO_OPTION) {
                return;
            }
        }

        if (opComboBox.getSelectedIndex()==2&&fromFiles.size()>2) {
            int ret = JOptionPane.showConfirmDialog(this, "Difference operation can only be performed" +
                    "on two files. The files other than the first two will be ignored." +
                    "Do you want to continue?",
                    null, JOptionPane.YES_NO_OPTION);
            if (ret==JOptionPane.NO_OPTION) {
                return;
            } else {
                for (int i=fromFiles.size()-1; i>=2; i--) {
                    fromFiles.remove(i);
                }
            }
        }

        //Reading phospho data
        ArrayList<Proteins> proteinsList = new ArrayList();
        for (String file : fromFiles) {
            PhosphoProteins phosphoData = new PhosphoProteinsImpl();
            PhosideXmlProteinsReader phosphoReader =
                    new PhosideXmlProteinsReader(file, phosphoData,
                    new PhosphoProteinFieldValueFormatter());

            ProteinsReadTask phosphoReadTask = new ProteinsReadTask(phosphoReader);
            TaskUtil.execute(phosphoReadTask);
            if (!phosphoReadTask.success()) {
                JOptionPane.showMessageDialog(this, "Failed to read the file:\n"+file);
                return;
            }

            proteinsList.add(phosphoData);
        }

        Proteins merged = PhosphoDataUtil.mergeProteins(proteinsList,opComboBox.getSelectedIndex());

        //Write to xml file
        PhosideXmlProteinsWriter writer = new PhosideXmlProteinsWriter(dirXml,
                new PhosphoProteinFieldValueFormatter());
        ProteinsWriteTask xmlWriteTask = new ProteinsWriteTask(merged, writer);
        TaskUtil.execute(xmlWriteTask);
        if (!xmlWriteTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to write the xml file");
            return;
        }

        JOptionPane.showMessageDialog(this, "Successfully merged the PHOSIDE XML files.");
        
        this.setVisible(false);
        this.dispose();
}//GEN-LAST:event_OKBtnActionPerformed

    private void cancelBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelBtnActionPerformed
        setVisible(false);
        dispose();
}//GEN-LAST:event_cancelBtnActionPerformed

    private void addFromButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addFromButtonActionPerformed
        JFileChooser fc = new JFileChooser(PhosideInit.defaultPath);
        ArrayList<String> exts = new ArrayList<String>(1);
        String ext = "xml";
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"PHOSIDE XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Add a PHOSIDE XML file...");
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            if (fromFiles.contains(filePath)) {
                JOptionPane.showMessageDialog(this, "This file has already been added.");
            }

            fromFiles.add(filePath);
            fromList.setListData(fromFiles);
        }
    }//GEN-LAST:event_addFromButtonActionPerformed

    private void rmvFromButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rmvFromButtonActionPerformed
        int[] idx = fromList.getSelectedIndices();
        for (int i=idx.length-1; i>=0; i--) {
            fromFiles.remove(idx[i]);
            fromList.setListData(fromFiles);
        }
    }//GEN-LAST:event_rmvFromButtonActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton OKBtn;
    private javax.swing.JList fromList;
    private javax.swing.JScrollPane fromScrollPane;
    private javax.swing.JComboBox opComboBox;
    private javax.swing.JTextField xmlFileTextField;
    // End of variables declaration//GEN-END:variables
    Vector<String> fromFiles = new Vector();
}
